<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="robots" content="noodp" />
        <title>设计模式之代理模式和Java中的代理以及JDK动态代理的实现原理 - MC&#39; blog</title><meta name="Description" content="MC&#39; Blog，不定期的技术分享"><meta property="og:title" content="设计模式之代理模式和Java中的代理以及JDK动态代理的实现原理" />
<meta property="og:description" content="设计模式之代理模式和Java中的代理 代理模式(Proxy Pottern)是一个使用频率很高的模式，其定义如下： Provide a surrogate or placegolder for another object to contol access to it." />
<meta property="og:type" content="article" />
<meta property="og:url" content="http://example.org/%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F/" /><meta property="og:image" content="http://example.org/logo.png"/><meta property="article:section" content="posts" />
<meta property="article:published_time" content="2018-10-13T22:07:00+08:00" />
<meta property="article:modified_time" content="2018-10-13T22:07:00+08:00" /><meta property="og:site_name" content="MC&#39; Blog" />
<meta name="twitter:card" content="summary_large_image"/>
<meta name="twitter:image" content="http://example.org/logo.png"/>

<meta name="twitter:title" content="设计模式之代理模式和Java中的代理以及JDK动态代理的实现原理"/>
<meta name="twitter:description" content="设计模式之代理模式和Java中的代理 代理模式(Proxy Pottern)是一个使用频率很高的模式，其定义如下： Provide a surrogate or placegolder for another object to contol access to it."/>
<meta name="application-name" content="MC&#39; Blog">
<meta name="apple-mobile-web-app-title" content="MC&#39; Blog"><meta name="theme-color" content="#ffffff"><meta name="msapplication-TileColor" content="#da532c"><link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
        <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
        <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"><link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"><link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5"><link rel="manifest" href="/site.webmanifest"><link rel="canonical" href="http://example.org/%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F/" /><link rel="prev" href="http://example.org/java%E5%B9%B6%E5%8F%91%E4%B9%8B%E6%97%A0%E9%94%81/" /><link rel="next" href="http://example.org/%E5%8E%9F%E5%9E%8B%E6%A8%A1%E5%BC%8F/" /><link rel="stylesheet" href="/css/style.min.css"><link rel="preload" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.1.1/css/all.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
        <noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.1.1/css/all.min.css"></noscript><link rel="preload" href="https://cdn.jsdelivr.net/npm/animate.css@4.1.1/animate.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
        <noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/animate.css@4.1.1/animate.min.css"></noscript><script type="application/ld+json">
    {
        "@context": "http://schema.org",
        "@type": "BlogPosting",
        "headline": "设计模式之代理模式和Java中的代理以及JDK动态代理的实现原理",
        "inLanguage": "zh-CN",
        "mainEntityOfPage": {
            "@type": "WebPage",
            "@id": "http:\/\/example.org\/%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F\/"
        },"image": ["http:\/\/example.org\/images\/Apple-Devices-Preview.png"],"genre": "posts","keywords": "设计模式","wordcount":  3984 ,
        "url": "http:\/\/example.org\/%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F\/","datePublished": "2018-10-13T22:07:00+08:00","dateModified": "2018-10-13T22:07:00+08:00","license": "This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.","publisher": {
            "@type": "Organization",
            "name": "xxxx","logo": {
                    "@type": "ImageObject",
                    "url": "http:\/\/example.org\/images\/avatar.png",
                    "width":  528 ,
                    "height":  560 
                }},"author": {
                "@type": "Person",
                "name": "MC"
            },"description": ""
    }
    </script></head>
    <body data-header-desktop="fixed" data-header-mobile="auto"><script type="text/javascript">(window.localStorage && localStorage.getItem('theme') ? localStorage.getItem('theme') === 'dark' : ('auto' === 'auto' ? window.matchMedia('(prefers-color-scheme: dark)').matches : 'auto' === 'dark')) && document.body.setAttribute('theme', 'dark');</script>

        <div id="mask"></div><div class="wrapper"><header class="desktop" id="header-desktop">
    <div class="header-wrapper">
        <div class="header-title">
            <a href="/" title="MC&#39; blog"><span class="header-title-pre"><i class='far fa-kiss-wink-heart fa-fw' aria-hidden='true'></i></span>MC&#39; Blog</a>
        </div>
        <div class="menu">
            <div class="menu-inner"><a class="menu-item" href="/posts/"> 所有文章 </a><a class="menu-item" href="/tags/"> 标签 </a><a class="menu-item" href="/categories/"> 分类 </a><a class="menu-item" href="/categories/documentation/"> 文档 </a><a class="menu-item" href="/about/"> 关于 </a><a class="menu-item" href="https://github.com/woxin123" title="GitHub" rel="noopener noreffer" target="_blank"><i class='fab fa-github fa-fw' aria-hidden='true'></i>  </a><span class="menu-item delimiter"></span><span class="menu-item search" id="search-desktop">
                        <input type="text" placeholder="搜索文章标题或内容..." id="search-input-desktop">
                        <a href="javascript:void(0);" class="search-button search-toggle" id="search-toggle-desktop" title="搜索">
                            <i class="fas fa-search fa-fw" aria-hidden="true"></i>
                        </a>
                        <a href="javascript:void(0);" class="search-button search-clear" id="search-clear-desktop" title="清空">
                            <i class="fas fa-times-circle fa-fw" aria-hidden="true"></i>
                        </a>
                        <span class="search-button search-loading" id="search-loading-desktop">
                            <i class="fas fa-spinner fa-fw fa-spin" aria-hidden="true"></i>
                        </span>
                    </span><a href="javascript:void(0);" class="menu-item theme-switch" title="切换主题">
                    <i class="fas fa-adjust fa-fw" aria-hidden="true"></i>
                </a></div>
        </div>
    </div>
</header><header class="mobile" id="header-mobile">
    <div class="header-container">
        <div class="header-wrapper">
            <div class="header-title">
                <a href="/" title="MC&#39; blog"><span class="header-title-pre"><i class='far fa-kiss-wink-heart fa-fw' aria-hidden='true'></i></span>MC&#39; Blog</a>
            </div>
            <div class="menu-toggle" id="menu-toggle-mobile">
                <span></span><span></span><span></span>
            </div>
        </div>
        <div class="menu" id="menu-mobile"><div class="search-wrapper">
                    <div class="search mobile" id="search-mobile">
                        <input type="text" placeholder="搜索文章标题或内容..." id="search-input-mobile">
                        <a href="javascript:void(0);" class="search-button search-toggle" id="search-toggle-mobile" title="搜索">
                            <i class="fas fa-search fa-fw" aria-hidden="true"></i>
                        </a>
                        <a href="javascript:void(0);" class="search-button search-clear" id="search-clear-mobile" title="清空">
                            <i class="fas fa-times-circle fa-fw" aria-hidden="true"></i>
                        </a>
                        <span class="search-button search-loading" id="search-loading-mobile">
                            <i class="fas fa-spinner fa-fw fa-spin" aria-hidden="true"></i>
                        </span>
                    </div>
                    <a href="javascript:void(0);" class="search-cancel" id="search-cancel-mobile">
                        取消
                    </a>
                </div><a class="menu-item" href="/posts/" title="">所有文章</a><a class="menu-item" href="/tags/" title="">标签</a><a class="menu-item" href="/categories/" title="">分类</a><a class="menu-item" href="/categories/documentation/" title="">文档</a><a class="menu-item" href="/about/" title="">关于</a><a class="menu-item" href="https://github.com/woxin123" title="GitHub" rel="noopener noreffer" target="_blank"><i class='fab fa-github fa-fw' aria-hidden='true'></i></a><a href="javascript:void(0);" class="menu-item theme-switch" title="切换主题">
                <i class="fas fa-adjust fa-fw" aria-hidden="true"></i>
            </a></div>
    </div>
</header><div class="search-dropdown desktop">
        <div id="search-dropdown-desktop"></div>
    </div>
    <div class="search-dropdown mobile">
        <div id="search-dropdown-mobile"></div>
    </div><main class="main">
                <div class="container"><div class="toc" id="toc-auto">
            <h2 class="toc-title">目录</h2>
            <div class="toc-content" id="toc-content-auto"></div>
        </div><article class="page single"><h1 class="single-title animate__animated animate__flipInX">设计模式之代理模式和Java中的代理以及JDK动态代理的实现原理</h1><div class="post-meta">
            <div class="post-meta-line"><span class="post-author"><a href="/" title="Author" rel="author" class="author"><i class="fas fa-user-circle fa-fw" aria-hidden="true"></i>MC</a></span>&nbsp;<span class="post-category">收录于 <a href="/categories/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"><i class="far fa-folder fa-fw" aria-hidden="true"></i>设计模式</a></span></div>
            <div class="post-meta-line"><i class="far fa-calendar-alt fa-fw" aria-hidden="true"></i>&nbsp;<time datetime="2018-10-13">2018-10-13</time>&nbsp;<i class="fas fa-pencil-alt fa-fw" aria-hidden="true"></i>&nbsp;约 3984 字&nbsp;
                <i class="far fa-clock fa-fw" aria-hidden="true"></i>&nbsp;预计阅读 8 分钟&nbsp;<span id="/%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F/" class="leancloud_visitors" data-flag-title="设计模式之代理模式和Java中的代理以及JDK动态代理的实现原理">
                        <i class="far fa-eye fa-fw" aria-hidden="true"></i>&nbsp;<span class=leancloud-visitors-count></span>&nbsp;次阅读
                    </span>&nbsp;</div>
        </div><div class="details toc" id="toc-static"  data-kept="">
                <div class="details-summary toc-title">
                    <span>目录</span>
                    <span><i class="details-icon fas fa-angle-right" aria-hidden="true"></i></span>
                </div>
                <div class="details-content toc-content" id="toc-content-static"><nav id="TableOfContents">
  <ul>
    <li><a href="#代理模式的实现">代理模式的实现</a>
      <ul>
        <li><a href="#静态代理">静态代理</a></li>
        <li><a href="#代理模型的优点">代理模型的优点</a></li>
        <li><a href="#动态代理">动态代理</a>
          <ul>
            <li><a href="#jdk的动态代理">jdk的动态代理</a></li>
          </ul>
        </li>
      </ul>
    </li>
    <li><a href="#cglib的动态代理">cglib的动态代理</a></li>
    <li><a href="#关于jdk的动态代理">关于JDK的动态代理</a></li>
  </ul>
</nav></div>
            </div><div class="content" id="content"><h1 id="设计模式之代理模式和java中的代理">设计模式之代理模式和Java中的代理</h1>
<p>代理模式(Proxy Pottern)是一个使用频率很高的模式，其定义如下：</p>
<blockquote>
<p>Provide a surrogate or placegolder for another object to contol access to it.(为其他对象提供一种代理以控制这个对象的访问。)</p>
</blockquote>
<p>代理模式在很多的开源项目中出现，基本上一些只需要提供接口，就能访问到具体内容的都是通过代理实现的。</p>
<p>代理模式中涉及的角色如下：</p>
<ul>
<li>Subject 抽象主体角色
这个可以是一个抽象的接口，也可以是一个普通的类。</li>
<li>RealSubject 具体主体角色
也叫作委托角色，被代理的类，是业务逻辑的具体执行者。</li>
<li>Proxy代理主体角色
也叫作委托类、代理类。它负责对真实角色的应用，把所有抽象主题类定义的方法限制委托给真实的主体角色实现。并在真实主体角色处理完毕后做预处理和善后工作。
<img
        class="lazyload"
        src="/svg/loading.min.svg"
        data-src="https://img-blog.csdn.net/20181013220439595?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N0YXJleHBsb2Rl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70"
        data-srcset="https://img-blog.csdn.net/20181013220439595?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N0YXJleHBsb2Rl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70, https://img-blog.csdn.net/20181013220439595?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N0YXJleHBsb2Rl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70 1.5x, https://img-blog.csdn.net/20181013220439595?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N0YXJleHBsb2Rl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70 2x"
        data-sizes="auto"
        alt="https://img-blog.csdn.net/20181013220439595?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N0YXJleHBsb2Rl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70"
        title="代理模式原型图" /></li>
</ul>
<h2 id="代理模式的实现">代理模式的实现</h2>
<p>代理模式有两种实现，一种是静态代理，另一种是动态代理。下面讲一下这两种代理模式。</p>
<h3 id="静态代理">静态代理</h3>
<p>静态代理的过程就是上面UML图的实现。
Subject接口如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="err">public</span> <span class="err">interface</span> <span class="err">Subject</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="err">void</span> <span class="err">request();</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>RealSubject实现了Subject，如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">RealSubject</span> <span class="kd">implements</span> <span class="n">Subject</span><span class="o">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">request</span><span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// 这里写一些业务逻辑
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>RealSubject是真正业务实现类，代理模型的核心就在代理类上，代理类如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Proxy</span> <span class="kd">implements</span> <span class="n">Subject</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm">     * 要代理的类
</span></span></span><span class="line"><span class="cl"><span class="cm">     */</span>
</span></span><span class="line"><span class="cl">    <span class="kd">private</span> <span class="n">Subject</span> <span class="n">subject</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="nf">Proxy</span><span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">this</span><span class="o">.</span><span class="na">subject</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Proxy</span><span class="o">();</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm">     * 通过构造函数传递代理类
</span></span></span><span class="line"><span class="cl"><span class="cm">     */</span>
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="nf">Proxy</span><span class="o">(</span><span class="n">Subject</span><span class="o">...</span> <span class="n">subjects</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm">     * 实现接口中定义的方法
</span></span></span><span class="line"><span class="cl"><span class="cm">     */</span>
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">request</span><span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">before</span><span class="o">();</span>
</span></span><span class="line"><span class="cl">        <span class="k">this</span><span class="o">.</span><span class="na">subject</span><span class="o">.</span><span class="na">request</span><span class="o">();</span>
</span></span><span class="line"><span class="cl">        <span class="n">after</span><span class="o">();</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm">     * 预处理
</span></span></span><span class="line"><span class="cl"><span class="cm">     */</span>
</span></span><span class="line"><span class="cl">    <span class="kd">private</span> <span class="kt">void</span> <span class="nf">before</span><span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm">     * 后处理
</span></span></span><span class="line"><span class="cl"><span class="cm">     */</span>
</span></span><span class="line"><span class="cl">    <span class="kd">private</span> <span class="kt">void</span> <span class="nf">after</span><span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="代理模型的优点">代理模型的优点</h3>
<ul>
<li>职责清晰
真实的角色实现的就是业务逻辑，而不关心其他非本职责的事务，通过后期的处理完成事务。</li>
<li>高可扩展性
无论被代理的对象如何改变，只要代理类和被代理的类都实现了同一个接口，所以即使修改了角色类，代理类也不用修改。</li>
</ul>
<h3 id="动态代理">动态代理</h3>
<p>Java中的动态代理的实现有两种：</p>
<ol>
<li>jdk动态代理，jdk中的动态代理是通过反射机制实现的。</li>
<li>cglib的动态代理，cglib动态代理底层是通过asm来实现的，cglib动态代理应用的更加广泛，因为效率比较高。</li>
</ol>
<h4 id="jdk的动态代理">jdk的动态代理</h4>
<p>下面通过一个用户登录的简单案例，来讲一下动态代理的使用。</p>
<p>用户类</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">User</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">private</span> <span class="kt">int</span> <span class="n">id</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">    <span class="kd">private</span> <span class="n">String</span> <span class="n">name</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="nf">User</span><span class="o">(</span><span class="kt">int</span> <span class="n">id</span><span class="o">,</span> <span class="n">String</span> <span class="n">name</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">this</span><span class="o">.</span><span class="na">id</span> <span class="o">=</span> <span class="n">id</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">this</span><span class="o">.</span><span class="na">name</span> <span class="o">=</span> <span class="n">name</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="kt">int</span> <span class="nf">getId</span><span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">id</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">setId</span><span class="o">(</span><span class="kt">int</span> <span class="n">id</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">this</span><span class="o">.</span><span class="na">id</span> <span class="o">=</span> <span class="n">id</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="n">String</span> <span class="nf">getName</span><span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">name</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">setName</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">this</span><span class="o">.</span><span class="na">name</span> <span class="o">=</span> <span class="n">name</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>用户服务类</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">interface</span> <span class="nc">UserService</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">boolean</span> <span class="nf">login</span><span class="o">(</span><span class="kt">int</span> <span class="n">id</span><span class="o">);</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>用户服务的实现类</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">UserServiceImpl</span> <span class="kd">implements</span> <span class="n">UserService</span><span class="o">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">private</span> <span class="kd">static</span> <span class="n">Map</span><span class="o">&lt;</span><span class="n">Integer</span><span class="o">,</span> <span class="n">User</span><span class="o">&gt;</span> <span class="n">users</span> <span class="o">=</span> <span class="k">new</span> <span class="n">HashMap</span><span class="o">&lt;&gt;();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">static</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">users</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="k">new</span> <span class="n">User</span><span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="s">&#34;张三&#34;</span><span class="o">));</span>
</span></span><span class="line"><span class="cl">        <span class="n">users</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="k">new</span> <span class="n">User</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="s">&#34;李四&#34;</span><span class="o">));</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nd">@Override</span>
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">login</span><span class="o">(</span><span class="kt">int</span> <span class="n">id</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="o">(</span><span class="n">users</span><span class="o">.</span><span class="na">containsKey</span><span class="o">(</span><span class="n">id</span><span class="o">))</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="kc">true</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="kc">false</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>使用JDK作为代理：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">UserServiceInvocationHandler</span> <span class="kd">implements</span> <span class="n">InvocationHandler</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">private</span> <span class="n">UserService</span> <span class="n">userService</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="n">UserService</span> <span class="nf">bind</span><span class="o">(</span><span class="n">UserService</span> <span class="n">userService</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">this</span><span class="o">.</span><span class="na">userService</span> <span class="o">=</span> <span class="n">userService</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="o">(</span><span class="n">UserService</span><span class="o">)</span> <span class="n">Proxy</span><span class="o">.</span><span class="na">newProxyInstance</span><span class="o">(</span><span class="n">userService</span><span class="o">.</span><span class="na">getClass</span><span class="o">().</span><span class="na">getClassLoader</span><span class="o">()</span>
</span></span><span class="line"><span class="cl">                <span class="o">,</span> <span class="n">userService</span><span class="o">.</span><span class="na">getClass</span><span class="o">().</span><span class="na">getInterfaces</span><span class="o">(),</span> <span class="k">this</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nd">@Override</span>
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="n">Object</span> <span class="nf">invoke</span><span class="o">(</span><span class="n">Object</span> <span class="n">proxy</span><span class="o">,</span> <span class="n">Method</span> <span class="n">method</span><span class="o">,</span> <span class="n">Object</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">Throwable</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="o">(</span><span class="n">method</span><span class="o">.</span><span class="na">getName</span><span class="o">().</span><span class="na">equals</span><span class="o">(</span><span class="s">&#34;login&#34;</span><span class="o">))</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">before</span><span class="o">(</span><span class="n">args</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">            <span class="kt">boolean</span> <span class="n">result</span> <span class="o">=</span> <span class="o">(</span><span class="kt">boolean</span><span class="o">)</span> <span class="n">method</span><span class="o">.</span><span class="na">invoke</span><span class="o">(</span><span class="n">userService</span><span class="o">,</span> <span class="n">args</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">            <span class="n">after</span><span class="o">(</span><span class="n">result</span><span class="o">,</span> <span class="n">args</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="n">result</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="kc">null</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">private</span> <span class="kt">void</span> <span class="nf">before</span><span class="o">(</span><span class="n">Object</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">&#34;id为&#34;</span> <span class="o">+</span> <span class="n">args</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span> <span class="o">+</span> <span class="s">&#34;的用户尝试登录&#34;</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">private</span> <span class="kt">void</span> <span class="nf">after</span><span class="o">(</span><span class="kt">boolean</span> <span class="n">result</span><span class="o">,</span> <span class="n">Object</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="o">(</span><span class="n">result</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">&#34;id为&#34;</span> <span class="o">+</span> <span class="n">args</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span> <span class="o">+</span> <span class="s">&#34;的用户登录成功&#34;</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">&#34;id为&#34;</span> <span class="o">+</span> <span class="n">args</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span> <span class="o">+</span> <span class="s">&#34;的用户登录失败&#34;</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>主类：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Run</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="n">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">UserServiceInvocationHandler</span> <span class="n">proxy</span> <span class="o">=</span> <span class="k">new</span> <span class="n">UserServiceInvocationHandler</span><span class="o">();</span>
</span></span><span class="line"><span class="cl">        <span class="n">UserService</span> <span class="n">userService</span> <span class="o">=</span> <span class="n">proxy</span><span class="o">.</span><span class="na">bind</span><span class="o">(</span><span class="k">new</span> <span class="n">UserServiceImpl</span><span class="o">());</span>
</span></span><span class="line"><span class="cl">        <span class="n">userService</span><span class="o">.</span><span class="na">login</span><span class="o">(</span><span class="mi">1</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">userService</span><span class="o">.</span><span class="na">login</span><span class="o">(</span><span class="mi">5</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="cglib的动态代理">cglib的动态代理</h2>
<p>JDK动态代理机制只能代理接口，而不能代理类(class)，而cglib可以，它的原理是对指定的目标生成一个子类，并覆盖其中的方法实现增强。cglib采用的是继承，所以不能对final修改的类进行代理。</p>
<p>cglib的代理类：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">CglibProxy</span> <span class="kd">implements</span> <span class="n">MethodInterceptor</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">private</span> <span class="n">Object</span> <span class="n">target</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="n">Object</span> <span class="nf">getInstance</span><span class="o">(</span><span class="n">Object</span> <span class="n">target</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">this</span><span class="o">.</span><span class="na">target</span> <span class="o">=</span> <span class="n">target</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">Enhancer</span> <span class="n">enhancer</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Enhancer</span><span class="o">();</span>
</span></span><span class="line"><span class="cl">        <span class="n">enhancer</span><span class="o">.</span><span class="na">setSuperclass</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">target</span><span class="o">.</span><span class="na">getClass</span><span class="o">());</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// 回调方法
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="n">enhancer</span><span class="o">.</span><span class="na">setCallback</span><span class="o">(</span><span class="k">this</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// 创建代理对象
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="k">return</span> <span class="n">enhancer</span><span class="o">.</span><span class="na">create</span><span class="o">();</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nd">@Override</span>
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="n">Object</span> <span class="nf">intercept</span><span class="o">(</span><span class="n">Object</span> <span class="n">o</span><span class="o">,</span> <span class="n">Method</span> <span class="n">method</span><span class="o">,</span> <span class="n">Object</span><span class="o">[]</span> <span class="n">objects</span><span class="o">,</span> <span class="n">MethodProxy</span> <span class="n">methodProxy</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">Throwable</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="o">(</span><span class="n">method</span><span class="o">.</span><span class="na">getName</span><span class="o">().</span><span class="na">equals</span><span class="o">(</span><span class="s">&#34;login&#34;</span><span class="o">))</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">before</span><span class="o">(</span><span class="n">objects</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">            <span class="kt">boolean</span> <span class="n">result</span> <span class="o">=</span> <span class="o">(</span><span class="kt">boolean</span><span class="o">)</span> <span class="n">methodProxy</span><span class="o">.</span><span class="na">invokeSuper</span><span class="o">(</span><span class="n">o</span><span class="o">,</span> <span class="n">objects</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">            <span class="n">after</span><span class="o">(</span><span class="n">result</span><span class="o">,</span> <span class="n">objects</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="n">result</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="kc">null</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">private</span> <span class="kt">void</span> <span class="nf">before</span><span class="o">(</span><span class="n">Object</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">&#34;id为&#34;</span> <span class="o">+</span> <span class="n">args</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span> <span class="o">+</span> <span class="s">&#34;的用户尝试登录&#34;</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">private</span> <span class="kt">void</span> <span class="nf">after</span><span class="o">(</span><span class="kt">boolean</span> <span class="n">result</span><span class="o">,</span> <span class="n">Object</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="o">(</span><span class="n">result</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">&#34;id为&#34;</span> <span class="o">+</span> <span class="n">args</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span> <span class="o">+</span> <span class="s">&#34;的用户登录成功&#34;</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">&#34;id为&#34;</span> <span class="o">+</span> <span class="n">args</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span> <span class="o">+</span> <span class="s">&#34;的用户登录失败&#34;</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>cglib的调用类：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">RunCglib</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="n">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">CglibProxy</span> <span class="n">cglibProxy</span> <span class="o">=</span> <span class="k">new</span> <span class="n">CglibProxy</span><span class="o">();</span>
</span></span><span class="line"><span class="cl">        <span class="n">UserService</span> <span class="n">userService</span> <span class="o">=</span> <span class="o">(</span><span class="n">UserService</span><span class="o">)</span> <span class="n">cglibProxy</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="k">new</span> <span class="n">UserServiceImpl</span><span class="o">());</span>
</span></span><span class="line"><span class="cl">        <span class="n">userService</span><span class="o">.</span><span class="na">login</span><span class="o">(</span><span class="mi">1</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">userService</span><span class="o">.</span><span class="na">login</span><span class="o">(</span><span class="mi">3</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="关于jdk的动态代理">关于JDK的动态代理</h2>
<p>将JDK中的<code>sun.misc.ProxyGenerator.saveGeneratedFiles</code>属性设置为true，会将代理类生成的字节码内容保存在项目的目录中，文件名为<code>$Proxy0.class</code>。
<img
        class="lazyload"
        src="/svg/loading.min.svg"
        data-src="https://img-blog.csdn.net/20181013220610801?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N0YXJleHBsb2Rl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70"
        data-srcset="https://img-blog.csdn.net/20181013220610801?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N0YXJleHBsb2Rl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70, https://img-blog.csdn.net/20181013220610801?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N0YXJleHBsb2Rl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70 1.5x, https://img-blog.csdn.net/20181013220610801?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N0YXJleHBsb2Rl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70 2x"
        data-sizes="auto"
        alt="https://img-blog.csdn.net/20181013220610801?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N0YXJleHBsb2Rl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70"
        title="$Proxy0.class" /></p>
<p>PS:我使用的是Maven创建的项目，然后这个文件没有出现，然后使用javac的多文件编译可以。这里如果IDE编译后没有出现这个类，尝试使用javac编译。</p>
<p>动态代理的过程中涉及到以下的类：</p>
<ol>
<li><code>java.lang.reflect.Proxy</code></li>
<li><code>java.lang.reflect.InvocationHandler</code></li>
<li><code>java.lang.reflect.WeakCache</code></li>
<li><code>sun.misc.ProxyGenerator</code></li>
</ol>
<p>代理过程的第一步是使用<code>newProxyInstace()</code>创建一个Proxy对象。下面来看下它的源码：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="nd">@CallerSensitive</span>
</span></span><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">static</span> <span class="n">Object</span> <span class="nf">newProxyInstance</span><span class="o">(</span><span class="n">ClassLoader</span> <span class="n">loader</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">                                      <span class="n">Class</span><span class="o">&lt;?&gt;[]</span> <span class="n">interfaces</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">                                      <span class="n">InvocationHandler</span> <span class="n">h</span><span class="o">)</span>
</span></span><span class="line"><span class="cl">    <span class="kd">throws</span> <span class="n">IllegalArgumentException</span>
</span></span><span class="line"><span class="cl"><span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 这里是判断InvocationHandler是否为空
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">Objects</span><span class="o">.</span><span class="na">requireNonNull</span><span class="o">(</span><span class="n">h</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// clone一份接口
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kd">final</span> <span class="n">Class</span><span class="o">&lt;?&gt;[]</span> <span class="n">intfs</span> <span class="o">=</span> <span class="n">interfaces</span><span class="o">.</span><span class="na">clone</span><span class="o">();</span>
</span></span><span class="line"><span class="cl">    <span class="kd">final</span> <span class="n">SecurityManager</span> <span class="n">sm</span> <span class="o">=</span> <span class="n">System</span><span class="o">.</span><span class="na">getSecurityManager</span><span class="o">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="o">(</span><span class="n">sm</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">checkProxyAccess</span><span class="o">(</span><span class="n">Reflection</span><span class="o">.</span><span class="na">getCallerClass</span><span class="o">(),</span> <span class="n">loader</span><span class="o">,</span> <span class="n">intfs</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">    <span class="cm">/*
</span></span></span><span class="line"><span class="cl"><span class="cm">     * 生成接口的代理类的字节码
</span></span></span><span class="line"><span class="cl"><span class="cm">     * Look up or generate the designated proxy class.
</span></span></span><span class="line"><span class="cl"><span class="cm">     */</span>
</span></span><span class="line"><span class="cl">    <span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">cl</span> <span class="o">=</span> <span class="n">getProxyClass0</span><span class="o">(</span><span class="n">loader</span><span class="o">,</span> <span class="n">intfs</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">    <span class="cm">/*
</span></span></span><span class="line"><span class="cl"><span class="cm">     * 使用自定义的InvocationHandler作为参数，调用构造方法获取代理类对象
</span></span></span><span class="line"><span class="cl"><span class="cm">     * Invoke its constructor with the designated invocation handler.
</span></span></span><span class="line"><span class="cl"><span class="cm">     */</span>
</span></span><span class="line"><span class="cl">    <span class="k">try</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="o">(</span><span class="n">sm</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">checkNewProxyPermission</span><span class="o">(</span><span class="n">Reflection</span><span class="o">.</span><span class="na">getCallerClass</span><span class="o">(),</span> <span class="n">cl</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span>
</span></span><span class="line"><span class="cl">        <span class="kd">final</span> <span class="n">Constructor</span><span class="o">&lt;?&gt;</span> <span class="n">cons</span> <span class="o">=</span> <span class="n">cl</span><span class="o">.</span><span class="na">getConstructor</span><span class="o">(</span><span class="n">constructorParams</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">        <span class="kd">final</span> <span class="n">InvocationHandler</span> <span class="n">ih</span> <span class="o">=</span> <span class="n">h</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="o">(!</span><span class="n">Modifier</span><span class="o">.</span><span class="na">isPublic</span><span class="o">(</span><span class="n">cl</span><span class="o">.</span><span class="na">getModifiers</span><span class="o">()))</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">AccessController</span><span class="o">.</span><span class="na">doPrivileged</span><span class="o">(</span><span class="k">new</span> <span class="n">PrivilegedAction</span><span class="o">&lt;</span><span class="n">Void</span><span class="o">&gt;()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">                <span class="kd">public</span> <span class="n">Void</span> <span class="nf">run</span><span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">                    <span class="n">cons</span><span class="o">.</span><span class="na">setAccessible</span><span class="o">(</span><span class="kc">true</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">                    <span class="k">return</span> <span class="kc">null</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">                <span class="o">}</span>
</span></span><span class="line"><span class="cl">            <span class="o">});</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">cons</span><span class="o">.</span><span class="na">newInstance</span><span class="o">(</span><span class="k">new</span> <span class="n">Object</span><span class="o">[]{</span><span class="n">h</span><span class="o">});</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">IllegalAccessException</span><span class="o">|</span><span class="n">InstantiationException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">throw</span> <span class="k">new</span> <span class="n">InternalError</span><span class="o">(</span><span class="n">e</span><span class="o">.</span><span class="na">toString</span><span class="o">(),</span> <span class="n">e</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">InvocationTargetException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">Throwable</span> <span class="n">t</span> <span class="o">=</span> <span class="n">e</span><span class="o">.</span><span class="na">getCause</span><span class="o">();</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="o">(</span><span class="n">t</span> <span class="k">instanceof</span> <span class="n">RuntimeException</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">throw</span> <span class="o">(</span><span class="n">RuntimeException</span><span class="o">)</span> <span class="n">t</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">throw</span> <span class="k">new</span> <span class="n">InternalError</span><span class="o">(</span><span class="n">t</span><span class="o">.</span><span class="na">toString</span><span class="o">(),</span> <span class="n">t</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">NoSuchMethodException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">throw</span> <span class="k">new</span> <span class="n">InternalError</span><span class="o">(</span><span class="n">e</span><span class="o">.</span><span class="na">toString</span><span class="o">(),</span> <span class="n">e</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>newProxyInstace()方法中调用了getProxyClass0()方法生成了代理类的字节码文件。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">private</span> <span class="kd">static</span> <span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">getProxyClass0</span><span class="o">(</span><span class="n">ClassLoader</span> <span class="n">loader</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">                                       <span class="n">Class</span><span class="o">&lt;?&gt;...</span> <span class="n">interfaces</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 限定代理的接口不能超过65535个
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">if</span> <span class="o">(</span><span class="n">interfaces</span><span class="o">.</span><span class="na">length</span> <span class="o">&gt;</span> <span class="mi">65535</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">throw</span> <span class="k">new</span> <span class="n">IllegalArgumentException</span><span class="o">(</span><span class="s">&#34;interface limit exceeded&#34;</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// If the proxy class defined by the given loader implementing
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="c1">// the given interfaces exists, this will simply return the cached copy;
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="c1">// otherwise, it will create the proxy class via the ProxyClassFactory
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="c1">// 如果缓存中已经存在相应接口的代理类，直接返回；否则，使用ProxyClassFactory创建代理类
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">return</span> <span class="n">proxyClassCache</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">loader</span><span class="o">,</span> <span class="n">interfaces</span><span class="o">);</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>这里我们不关心缓存，只关心代理类是如何生成的。
这里使用的缓存是WeakCache，如果Cache中没有，则会调用ProxyClassFactory的apply方法创建一个代理类。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">  1
</span><span class="lnt">  2
</span><span class="lnt">  3
</span><span class="lnt">  4
</span><span class="lnt">  5
</span><span class="lnt">  6
</span><span class="lnt">  7
</span><span class="lnt">  8
</span><span class="lnt">  9
</span><span class="lnt"> 10
</span><span class="lnt"> 11
</span><span class="lnt"> 12
</span><span class="lnt"> 13
</span><span class="lnt"> 14
</span><span class="lnt"> 15
</span><span class="lnt"> 16
</span><span class="lnt"> 17
</span><span class="lnt"> 18
</span><span class="lnt"> 19
</span><span class="lnt"> 20
</span><span class="lnt"> 21
</span><span class="lnt"> 22
</span><span class="lnt"> 23
</span><span class="lnt"> 24
</span><span class="lnt"> 25
</span><span class="lnt"> 26
</span><span class="lnt"> 27
</span><span class="lnt"> 28
</span><span class="lnt"> 29
</span><span class="lnt"> 30
</span><span class="lnt"> 31
</span><span class="lnt"> 32
</span><span class="lnt"> 33
</span><span class="lnt"> 34
</span><span class="lnt"> 35
</span><span class="lnt"> 36
</span><span class="lnt"> 37
</span><span class="lnt"> 38
</span><span class="lnt"> 39
</span><span class="lnt"> 40
</span><span class="lnt"> 41
</span><span class="lnt"> 42
</span><span class="lnt"> 43
</span><span class="lnt"> 44
</span><span class="lnt"> 45
</span><span class="lnt"> 46
</span><span class="lnt"> 47
</span><span class="lnt"> 48
</span><span class="lnt"> 49
</span><span class="lnt"> 50
</span><span class="lnt"> 51
</span><span class="lnt"> 52
</span><span class="lnt"> 53
</span><span class="lnt"> 54
</span><span class="lnt"> 55
</span><span class="lnt"> 56
</span><span class="lnt"> 57
</span><span class="lnt"> 58
</span><span class="lnt"> 59
</span><span class="lnt"> 60
</span><span class="lnt"> 61
</span><span class="lnt"> 62
</span><span class="lnt"> 63
</span><span class="lnt"> 64
</span><span class="lnt"> 65
</span><span class="lnt"> 66
</span><span class="lnt"> 67
</span><span class="lnt"> 68
</span><span class="lnt"> 69
</span><span class="lnt"> 70
</span><span class="lnt"> 71
</span><span class="lnt"> 72
</span><span class="lnt"> 73
</span><span class="lnt"> 74
</span><span class="lnt"> 75
</span><span class="lnt"> 76
</span><span class="lnt"> 77
</span><span class="lnt"> 78
</span><span class="lnt"> 79
</span><span class="lnt"> 80
</span><span class="lnt"> 81
</span><span class="lnt"> 82
</span><span class="lnt"> 83
</span><span class="lnt"> 84
</span><span class="lnt"> 85
</span><span class="lnt"> 86
</span><span class="lnt"> 87
</span><span class="lnt"> 88
</span><span class="lnt"> 89
</span><span class="lnt"> 90
</span><span class="lnt"> 91
</span><span class="lnt"> 92
</span><span class="lnt"> 93
</span><span class="lnt"> 94
</span><span class="lnt"> 95
</span><span class="lnt"> 96
</span><span class="lnt"> 97
</span><span class="lnt"> 98
</span><span class="lnt"> 99
</span><span class="lnt">100
</span><span class="lnt">101
</span><span class="lnt">102
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">ProxyClassFactory</span>
</span></span><span class="line"><span class="cl">    <span class="kd">implements</span> <span class="n">BiFunction</span><span class="o">&lt;</span><span class="n">ClassLoader</span><span class="o">,</span> <span class="n">Class</span><span class="o">&lt;?&gt;[],</span> <span class="n">Class</span><span class="o">&lt;?&gt;&gt;</span>
</span></span><span class="line"><span class="cl"><span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// prefix for all proxy class names
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="c1">// 所有jdk代理类的前缀名
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">String</span> <span class="n">proxyClassNamePrefix</span> <span class="o">=</span> <span class="s">&#34;$Proxy&#34;</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// next number to use for generation of unique proxy class names
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="c1">// 一个无锁的long
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">AtomicLong</span> <span class="n">nextUniqueNumber</span> <span class="o">=</span> <span class="k">new</span> <span class="n">AtomicLong</span><span class="o">();</span>
</span></span><span class="line"><span class="cl">    <span class="nd">@Override</span>
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">apply</span><span class="o">(</span><span class="n">ClassLoader</span> <span class="n">loader</span><span class="o">,</span> <span class="n">Class</span><span class="o">&lt;?&gt;[]</span> <span class="n">interfaces</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">Map</span><span class="o">&lt;</span><span class="n">Class</span><span class="o">&lt;?&gt;,</span> <span class="n">Boolean</span><span class="o">&gt;</span> <span class="n">interfaceSet</span> <span class="o">=</span> <span class="k">new</span> <span class="n">IdentityHashMap</span><span class="o">&lt;&gt;(</span><span class="n">interfaces</span><span class="o">.</span><span class="na">length</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// 校验类加载器是否能通过接口名称加载该类
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="k">for</span> <span class="o">(</span><span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">intf</span> <span class="o">:</span> <span class="n">interfaces</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="cm">/*
</span></span></span><span class="line"><span class="cl"><span class="cm">             * Verify that the class loader resolves the name of this
</span></span></span><span class="line"><span class="cl"><span class="cm">             * interface to the same Class object.
</span></span></span><span class="line"><span class="cl"><span class="cm">             */</span>
</span></span><span class="line"><span class="cl">            <span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">interfaceClass</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">            <span class="k">try</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">                <span class="n">interfaceClass</span> <span class="o">=</span> <span class="n">Class</span><span class="o">.</span><span class="na">forName</span><span class="o">(</span><span class="n">intf</span><span class="o">.</span><span class="na">getName</span><span class="o">(),</span> <span class="kc">false</span><span class="o">,</span> <span class="n">loader</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">            <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">ClassNotFoundException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="o">}</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="o">(</span><span class="n">interfaceClass</span> <span class="o">!=</span> <span class="n">intf</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">throw</span> <span class="k">new</span> <span class="n">IllegalArgumentException</span><span class="o">(</span>
</span></span><span class="line"><span class="cl">                    <span class="n">intf</span> <span class="o">+</span> <span class="s">&#34; is not visible from class loader&#34;</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">            <span class="o">}</span>
</span></span><span class="line"><span class="cl">            <span class="cm">/*
</span></span></span><span class="line"><span class="cl"><span class="cm">             * 校验该类是否接口类型
</span></span></span><span class="line"><span class="cl"><span class="cm">             * Verify that the Class object actually represents an
</span></span></span><span class="line"><span class="cl"><span class="cm">             * interface.
</span></span></span><span class="line"><span class="cl"><span class="cm">             */</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="o">(!</span><span class="n">interfaceClass</span><span class="o">.</span><span class="na">isInterface</span><span class="o">())</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">throw</span> <span class="k">new</span> <span class="n">IllegalArgumentException</span><span class="o">(</span>
</span></span><span class="line"><span class="cl">                    <span class="n">interfaceClass</span><span class="o">.</span><span class="na">getName</span><span class="o">()</span> <span class="o">+</span> <span class="s">&#34; is not an interface&#34;</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">            <span class="o">}</span>
</span></span><span class="line"><span class="cl">            <span class="cm">/*
</span></span></span><span class="line"><span class="cl"><span class="cm">             * 校验接口是否重复
</span></span></span><span class="line"><span class="cl"><span class="cm">             * Verify that this interface is not a duplicate.
</span></span></span><span class="line"><span class="cl"><span class="cm">             */</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="o">(</span><span class="n">interfaceSet</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="n">interfaceClass</span><span class="o">,</span> <span class="n">Boolean</span><span class="o">.</span><span class="na">TRUE</span><span class="o">)</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">throw</span> <span class="k">new</span> <span class="n">IllegalArgumentException</span><span class="o">(</span>
</span></span><span class="line"><span class="cl">                    <span class="s">&#34;repeated interface: &#34;</span> <span class="o">+</span> <span class="n">interfaceClass</span><span class="o">.</span><span class="na">getName</span><span class="o">());</span>
</span></span><span class="line"><span class="cl">            <span class="o">}</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// 代理类的包名
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="n">String</span> <span class="n">proxyPkg</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>     <span class="c1">// package to define proxy class in
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="kt">int</span> <span class="n">accessFlags</span> <span class="o">=</span> <span class="n">Modifier</span><span class="o">.</span><span class="na">PUBLIC</span> <span class="o">|</span> <span class="n">Modifier</span><span class="o">.</span><span class="na">FINAL</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">        <span class="cm">/*
</span></span></span><span class="line"><span class="cl"><span class="cm">         * 对于非public类，代理类的包名和接口的包名相同
</span></span></span><span class="line"><span class="cl"><span class="cm">         * Record the package of a non-public proxy interface so that the
</span></span></span><span class="line"><span class="cl"><span class="cm">         * proxy class will be defined in the same package.  Verify that
</span></span></span><span class="line"><span class="cl"><span class="cm">         * all non-public proxy interfaces are in the same package.
</span></span></span><span class="line"><span class="cl"><span class="cm">         */</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="o">(</span><span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">intf</span> <span class="o">:</span> <span class="n">interfaces</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="kt">int</span> <span class="n">flags</span> <span class="o">=</span> <span class="n">intf</span><span class="o">.</span><span class="na">getModifiers</span><span class="o">();</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="o">(!</span><span class="n">Modifier</span><span class="o">.</span><span class="na">isPublic</span><span class="o">(</span><span class="n">flags</span><span class="o">))</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">                <span class="n">accessFlags</span> <span class="o">=</span> <span class="n">Modifier</span><span class="o">.</span><span class="na">FINAL</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">                <span class="n">String</span> <span class="n">name</span> <span class="o">=</span> <span class="n">intf</span><span class="o">.</span><span class="na">getName</span><span class="o">();</span>
</span></span><span class="line"><span class="cl">                <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="n">name</span><span class="o">.</span><span class="na">lastIndexOf</span><span class="o">(</span><span class="sc">&#39;.&#39;</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">                <span class="n">String</span> <span class="n">pkg</span> <span class="o">=</span> <span class="o">((</span><span class="n">n</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="o">)</span> <span class="o">?</span> <span class="s">&#34;&#34;</span> <span class="o">:</span> <span class="n">name</span><span class="o">.</span><span class="na">substring</span><span class="o">(</span><span class="mi">0</span><span class="o">,</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="o">));</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="o">(</span><span class="n">proxyPkg</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">                    <span class="n">proxyPkg</span> <span class="o">=</span> <span class="n">pkg</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">                <span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(!</span><span class="n">pkg</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">proxyPkg</span><span class="o">))</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">                    <span class="k">throw</span> <span class="k">new</span> <span class="n">IllegalArgumentException</span><span class="o">(</span>
</span></span><span class="line"><span class="cl">                        <span class="s">&#34;non-public interfaces from different packages&#34;</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">                <span class="o">}</span>
</span></span><span class="line"><span class="cl">            <span class="o">}</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="o">(</span><span class="n">proxyPkg</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="c1">// public的代理接口，使用com.sun.proxy包名
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>            <span class="c1">// if no non-public proxy interfaces, use com.sun.proxy package
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>            <span class="n">proxyPkg</span> <span class="o">=</span> <span class="n">ReflectUtil</span><span class="o">.</span><span class="na">PROXY_PACKAGE</span> <span class="o">+</span> <span class="s">&#34;.&#34;</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span>
</span></span><span class="line"><span class="cl">        <span class="cm">/*
</span></span></span><span class="line"><span class="cl"><span class="cm">         * 给代理类起一个名字
</span></span></span><span class="line"><span class="cl"><span class="cm">         * Choose a name for the proxy class to generate.
</span></span></span><span class="line"><span class="cl"><span class="cm">         */</span>
</span></span><span class="line"><span class="cl">        <span class="kt">long</span> <span class="n">num</span> <span class="o">=</span> <span class="n">nextUniqueNumber</span><span class="o">.</span><span class="na">getAndIncrement</span><span class="o">();</span>
</span></span><span class="line"><span class="cl">        <span class="n">String</span> <span class="n">proxyName</span> <span class="o">=</span> <span class="n">proxyPkg</span> <span class="o">+</span> <span class="n">proxyClassNamePrefix</span> <span class="o">+</span> <span class="n">num</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">        <span class="cm">/*
</span></span></span><span class="line"><span class="cl"><span class="cm">         * 这个方法是真正生成字节码的地方
</span></span></span><span class="line"><span class="cl"><span class="cm">         * Generate the specified proxy class.
</span></span></span><span class="line"><span class="cl"><span class="cm">         */</span>
</span></span><span class="line"><span class="cl">        <span class="kt">byte</span><span class="o">[]</span> <span class="n">proxyClassFile</span> <span class="o">=</span> <span class="n">ProxyGenerator</span><span class="o">.</span><span class="na">generateProxyClass</span><span class="o">(</span>
</span></span><span class="line"><span class="cl">            <span class="n">proxyName</span><span class="o">,</span> <span class="n">interfaces</span><span class="o">,</span> <span class="n">accessFlags</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">try</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="c1">// 使用类加载器将代理类的字节码加载到JVM中
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>            <span class="k">return</span> <span class="n">defineClass0</span><span class="o">(</span><span class="n">loader</span><span class="o">,</span> <span class="n">proxyName</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">                                <span class="n">proxyClassFile</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="n">proxyClassFile</span><span class="o">.</span><span class="na">length</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">ClassFormatError</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="cm">/*
</span></span></span><span class="line"><span class="cl"><span class="cm">             * A ClassFormatError here means that (barring bugs in the
</span></span></span><span class="line"><span class="cl"><span class="cm">             * proxy class generation code) there was some other
</span></span></span><span class="line"><span class="cl"><span class="cm">             * invalid aspect of the arguments supplied to the proxy
</span></span></span><span class="line"><span class="cl"><span class="cm">             * class creation (such as virtual machine limitations
</span></span></span><span class="line"><span class="cl"><span class="cm">             * exceeded).
</span></span></span><span class="line"><span class="cl"><span class="cm">             */</span>
</span></span><span class="line"><span class="cl">            <span class="k">throw</span> <span class="k">new</span> <span class="n">IllegalArgumentException</span><span class="o">(</span><span class="n">e</span><span class="o">.</span><span class="na">toString</span><span class="o">());</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>从上面的方法可以看出生成代理类实在ProxyGenerator中，但是该类没有开源（因为这个代理是sun公司的，从包名中就可以看出），可以通过反编译工具来看。如下:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">static</span> <span class="kt">byte</span><span class="o">[]</span> <span class="nf">generateProxyClass</span><span class="o">(</span><span class="kd">final</span> <span class="n">String</span> <span class="n">var0</span><span class="o">,</span> <span class="n">Class</span><span class="o">&lt;?&gt;[]</span> <span class="n">var1</span><span class="o">,</span> <span class="kt">int</span> <span class="n">var2</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">ProxyGenerator</span> <span class="n">var3</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ProxyGenerator</span><span class="o">(</span><span class="n">var0</span><span class="o">,</span> <span class="n">var1</span><span class="o">,</span> <span class="n">var2</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">    <span class="kd">final</span> <span class="kt">byte</span><span class="o">[]</span> <span class="n">var4</span> <span class="o">=</span> <span class="n">var3</span><span class="o">.</span><span class="na">generateClassFile</span><span class="o">();</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 是否存储在磁盘上
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">if</span> <span class="o">(</span><span class="n">saveGeneratedFiles</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// ,,,
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="o">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">var4</span><span class="o">;</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>这里设置<code>sum.misc.ProxyGenerator.saveGeneratedFiles</code>的值为true。</p>
<p>所以运行后就有$Proxy0.class这个文件，通过反编译后的内容如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span><span class="lnt">63
</span><span class="lnt">64
</span><span class="lnt">65
</span><span class="lnt">66
</span><span class="lnt">67
</span><span class="lnt">68
</span><span class="lnt">69
</span><span class="lnt">70
</span><span class="lnt">71
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nn">com.sun.proxy</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">java.lang.reflect.InvocationHandler</span><span class="o">;</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">java.lang.reflect.Method</span><span class="o">;</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">java.lang.reflect.Proxy</span><span class="o">;</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">java.lang.reflect.UndeclaredThrowableException</span><span class="o">;</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">top.mcwebsite.proxy_pattern.UserService</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">$Proxy0</span> <span class="kd">extends</span> <span class="n">Proxy</span> <span class="kd">implements</span> <span class="n">UserService</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">    <span class="kd">private</span> <span class="kd">static</span> <span class="n">Method</span> <span class="n">m1</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">    <span class="kd">private</span> <span class="kd">static</span> <span class="n">Method</span> <span class="n">m2</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">    <span class="kd">private</span> <span class="kd">static</span> <span class="n">Method</span> <span class="n">m0</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">    <span class="kd">private</span> <span class="kd">static</span> <span class="n">Method</span> <span class="n">m3</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="nf">$Proxy0</span><span class="o">(</span><span class="n">InvocationHandler</span> <span class="n">var1</span><span class="o">)</span> <span class="kd">throws</span>  <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="kd">super</span><span class="o">(</span><span class="n">var1</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="kd">final</span> <span class="kt">boolean</span> <span class="nf">equals</span><span class="o">(</span><span class="n">Object</span> <span class="n">var1</span><span class="o">)</span> <span class="kd">throws</span>  <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">try</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="o">(</span><span class="n">Boolean</span><span class="o">)</span><span class="kd">super</span><span class="o">.</span><span class="na">h</span><span class="o">.</span><span class="na">invoke</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="n">m1</span><span class="o">,</span> <span class="k">new</span> <span class="n">Object</span><span class="o">[]{</span><span class="n">var1</span><span class="o">});</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">RuntimeException</span> <span class="o">|</span> <span class="n">Error</span> <span class="n">var3</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">throw</span> <span class="n">var3</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">Throwable</span> <span class="n">var4</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">throw</span> <span class="k">new</span> <span class="n">UndeclaredThrowableException</span><span class="o">(</span><span class="n">var4</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="kd">final</span> <span class="n">String</span> <span class="nf">toString</span><span class="o">()</span> <span class="kd">throws</span>  <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">try</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="o">(</span><span class="n">String</span><span class="o">)</span><span class="kd">super</span><span class="o">.</span><span class="na">h</span><span class="o">.</span><span class="na">invoke</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="n">m2</span><span class="o">,</span> <span class="o">(</span><span class="n">Object</span><span class="o">[])</span><span class="kc">null</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">RuntimeException</span> <span class="o">|</span> <span class="n">Error</span> <span class="n">var2</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">throw</span> <span class="n">var2</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">Throwable</span> <span class="n">var3</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">throw</span> <span class="k">new</span> <span class="n">UndeclaredThrowableException</span><span class="o">(</span><span class="n">var3</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="kd">final</span> <span class="kt">int</span> <span class="nf">hashCode</span><span class="o">()</span> <span class="kd">throws</span>  <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">try</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="o">(</span><span class="n">Integer</span><span class="o">)</span><span class="kd">super</span><span class="o">.</span><span class="na">h</span><span class="o">.</span><span class="na">invoke</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="n">m0</span><span class="o">,</span> <span class="o">(</span><span class="n">Object</span><span class="o">[])</span><span class="kc">null</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">RuntimeException</span> <span class="o">|</span> <span class="n">Error</span> <span class="n">var2</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">throw</span> <span class="n">var2</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">Throwable</span> <span class="n">var3</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">throw</span> <span class="k">new</span> <span class="n">UndeclaredThrowableException</span><span class="o">(</span><span class="n">var3</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">public</span> <span class="kd">final</span> <span class="kt">boolean</span> <span class="nf">login</span><span class="o">(</span><span class="kt">int</span> <span class="n">var1</span><span class="o">)</span> <span class="kd">throws</span>  <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">try</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="o">(</span><span class="n">Boolean</span><span class="o">)</span><span class="kd">super</span><span class="o">.</span><span class="na">h</span><span class="o">.</span><span class="na">invoke</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="n">m3</span><span class="o">,</span> <span class="k">new</span> <span class="n">Object</span><span class="o">[]{</span><span class="n">var1</span><span class="o">});</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">RuntimeException</span> <span class="o">|</span> <span class="n">Error</span> <span class="n">var3</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">throw</span> <span class="n">var3</span><span class="o">;</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">Throwable</span> <span class="n">var4</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">throw</span> <span class="k">new</span> <span class="n">UndeclaredThrowableException</span><span class="o">(</span><span class="n">var4</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">static</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">try</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">m1</span> <span class="o">=</span> <span class="n">Class</span><span class="o">.</span><span class="na">forName</span><span class="o">(</span><span class="s">&#34;java.lang.Object&#34;</span><span class="o">).</span><span class="na">getMethod</span><span class="o">(</span><span class="s">&#34;equals&#34;</span><span class="o">,</span> <span class="n">Class</span><span class="o">.</span><span class="na">forName</span><span class="o">(</span><span class="s">&#34;java.lang.Object&#34;</span><span class="o">));</span>
</span></span><span class="line"><span class="cl">            <span class="n">m2</span> <span class="o">=</span> <span class="n">Class</span><span class="o">.</span><span class="na">forName</span><span class="o">(</span><span class="s">&#34;java.lang.Object&#34;</span><span class="o">).</span><span class="na">getMethod</span><span class="o">(</span><span class="s">&#34;toString&#34;</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">            <span class="n">m0</span> <span class="o">=</span> <span class="n">Class</span><span class="o">.</span><span class="na">forName</span><span class="o">(</span><span class="s">&#34;java.lang.Object&#34;</span><span class="o">).</span><span class="na">getMethod</span><span class="o">(</span><span class="s">&#34;hashCode&#34;</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">            <span class="n">m3</span> <span class="o">=</span> <span class="n">Class</span><span class="o">.</span><span class="na">forName</span><span class="o">(</span><span class="s">&#34;top.mcwebsite.proxy_pattern.UserService&#34;</span><span class="o">).</span><span class="na">getMethod</span><span class="o">(</span><span class="s">&#34;login&#34;</span><span class="o">,</span> <span class="n">Integer</span><span class="o">.</span><span class="na">TYPE</span><span class="o">);</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">NoSuchMethodException</span> <span class="n">var2</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">throw</span> <span class="k">new</span> <span class="n">NoSuchMethodError</span><span class="o">(</span><span class="n">var2</span><span class="o">.</span><span class="na">getMessage</span><span class="o">());</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">ClassNotFoundException</span> <span class="n">var3</span><span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">throw</span> <span class="k">new</span> <span class="n">NoClassDefFoundError</span><span class="o">(</span><span class="n">var3</span><span class="o">.</span><span class="na">getMessage</span><span class="o">());</span>
</span></span><span class="line"><span class="cl">        <span class="o">}</span>
</span></span><span class="line"><span class="cl">    <span class="o">}</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>代理类继承了Proxy，实现了指定的接口，所以jdk的代理类不能代理没有实现接口的类。代理类中重写了hashCode()，equals()和toString()方法。</p>
<p>代理类通过反射指定了代理类的所有方法。通过invoke执行了目标方法doSoemthing()。</p>
</div><div class="post-footer" id="post-footer">
    <div class="post-info">
        <div class="post-info-line">
            <div class="post-info-mod">
                <span>更新于 2018-10-13</span>
            </div></div>
        <div class="post-info-line">
            <div class="post-info-md"><span>
                            <a class="link-to-markdown" href="/%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F/index.md" target="_blank">阅读原始文档</a>
                        </span></div>
            <div class="post-info-share">
                <span><a href="javascript:void(0);" title="分享到 Twitter" data-sharer="twitter" data-url="http://example.org/%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F/" data-title="设计模式之代理模式和Java中的代理以及JDK动态代理的实现原理" data-hashtags="设计模式"><i class="fab fa-twitter fa-fw" aria-hidden="true"></i></a><a href="javascript:void(0);" title="分享到 Facebook" data-sharer="facebook" data-url="http://example.org/%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F/" data-hashtag="设计模式"><i class="fab fa-facebook-square fa-fw" aria-hidden="true"></i></a><a href="javascript:void(0);" title="分享到 Hacker News" data-sharer="hackernews" data-url="http://example.org/%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F/" data-title="设计模式之代理模式和Java中的代理以及JDK动态代理的实现原理"><i class="fab fa-hacker-news fa-fw" aria-hidden="true"></i></a><a href="javascript:void(0);" title="分享到 Line" data-sharer="line" data-url="http://example.org/%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F/" data-title="设计模式之代理模式和Java中的代理以及JDK动态代理的实现原理"><i data-svg-src="https://cdn.jsdelivr.net/npm/simple-icons@7.3.0/icons/line.svg" aria-hidden="true"></i></a><a href="javascript:void(0);" title="分享到 微博" data-sharer="weibo" data-url="http://example.org/%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F/" data-title="设计模式之代理模式和Java中的代理以及JDK动态代理的实现原理" data-ralateuid="xxxx"><i class="fab fa-weibo fa-fw" aria-hidden="true"></i></a></span>
            </div>
        </div>
    </div>

    <div class="post-info-more">
        <section class="post-tags"><i class="fas fa-tags fa-fw" aria-hidden="true"></i>&nbsp;<a href="/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/">设计模式</a></section>
        <section>
            <span><a href="javascript:void(0);" onclick="window.history.back();">返回</a></span>&nbsp;|&nbsp;<span><a href="/">主页</a></span>
        </section>
    </div>

    <div class="post-nav"><a href="/java%E5%B9%B6%E5%8F%91%E4%B9%8B%E6%97%A0%E9%94%81/" class="prev" rel="prev" title="Java并发编程之无锁"><i class="fas fa-angle-left fa-fw" aria-hidden="true"></i>Java并发编程之无锁</a>
            <a href="/%E5%8E%9F%E5%9E%8B%E6%A8%A1%E5%BC%8F/" class="next" rel="next" title="设计模式之原型模式——浅拷贝和深拷贝">设计模式之原型模式——浅拷贝和深拷贝<i class="fas fa-angle-right fa-fw" aria-hidden="true"></i></a></div>
</div>
<div id="comments"><div id="valine" class="comment"></div><noscript>
                Please enable JavaScript to view the comments powered by <a href="https://valine.js.org/">Valine</a>.
            </noscript></div></article></div>
            </main><footer class="footer">
        <div class="footer-container"><div class="footer-line">由 <a href="https://gohugo.io/" target="_blank" rel="noopener noreffer" title="Hugo 0.109.0">Hugo</a> 强力驱动 | 主题 - <a href="https://github.com/dillonzq/LoveIt" target="_blank" rel="noopener noreffer" title="LoveIt 0.2.11"><i class="far fa-kiss-wink-heart fa-fw" aria-hidden="true"></i> LoveIt</a>
                </div><div class="footer-line" itemscope itemtype="http://schema.org/CreativeWork"><i class="far fa-copyright fa-fw" aria-hidden="true"></i><span itemprop="copyrightYear">2023</span><span class="author" itemprop="copyrightHolder">&nbsp;<a href="/" target="_blank">MC</a></span>&nbsp;|&nbsp;<span class="license"><a rel="license external nofollow noopener noreffer" href="https://creativecommons.org/licenses/by-nc/4.0/" target="_blank">CC BY-NC 4.0</a></span></div>
        </div>
    </footer></div>

        <div id="fixed-buttons"><a href="#" id="back-to-top" class="fixed-button" title="回到顶部">
                <i class="fas fa-arrow-up fa-fw" aria-hidden="true"></i>
            </a><a href="#" id="view-comments" class="fixed-button" title="查看评论">
                <i class="fas fa-comment fa-fw" aria-hidden="true"></i>
            </a>
        </div><link rel="stylesheet" href="/lib/valine/valine.min.css"><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/valine@1.5.0/dist/Valine.min.js"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/autocomplete.js@0.38.1/dist/autocomplete.min.js"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/lunr@2.3.9/lunr.min.js"></script><script type="text/javascript" src="/lib/lunr/lunr.stemmer.support.min.js"></script><script type="text/javascript" src="/lib/lunr/lunr.zh.min.js"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/lazysizes@5.3.2/lazysizes.min.js"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/clipboard@2.0.11/dist/clipboard.min.js"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/sharer.js@0.5.1/sharer.min.js"></script><script type="text/javascript">window.config={"code":{"copyTitle":"复制到剪贴板","maxShownLines":50},"comment":{"valine":{"appId":"QGzwQXOqs5JOhN4RGPOkR2mR-MdYXbMMI","appKey":"WBmoGyJtbqUswvfLh6L8iEBr","avatar":"mp","el":"#valine","emojiCDN":"https://cdn.jsdelivr.net/npm/emoji-datasource-google@14.0.0/img/google/64/","emojiMaps":{"100":"1f4af.png","alien":"1f47d.png","anger":"1f4a2.png","angry":"1f620.png","anguished":"1f627.png","astonished":"1f632.png","black_heart":"1f5a4.png","blue_heart":"1f499.png","blush":"1f60a.png","bomb":"1f4a3.png","boom":"1f4a5.png","broken_heart":"1f494.png","brown_heart":"1f90e.png","clown_face":"1f921.png","cold_face":"1f976.png","cold_sweat":"1f630.png","confounded":"1f616.png","confused":"1f615.png","cry":"1f622.png","crying_cat_face":"1f63f.png","cupid":"1f498.png","dash":"1f4a8.png","disappointed":"1f61e.png","disappointed_relieved":"1f625.png","dizzy":"1f4ab.png","dizzy_face":"1f635.png","drooling_face":"1f924.png","exploding_head":"1f92f.png","expressionless":"1f611.png","face_vomiting":"1f92e.png","face_with_cowboy_hat":"1f920.png","face_with_hand_over_mouth":"1f92d.png","face_with_head_bandage":"1f915.png","face_with_monocle":"1f9d0.png","face_with_raised_eyebrow":"1f928.png","face_with_rolling_eyes":"1f644.png","face_with_symbols_on_mouth":"1f92c.png","face_with_thermometer":"1f912.png","fearful":"1f628.png","flushed":"1f633.png","frowning":"1f626.png","ghost":"1f47b.png","gift_heart":"1f49d.png","green_heart":"1f49a.png","grimacing":"1f62c.png","grin":"1f601.png","grinning":"1f600.png","hankey":"1f4a9.png","hear_no_evil":"1f649.png","heart":"2764-fe0f.png","heart_decoration":"1f49f.png","heart_eyes":"1f60d.png","heart_eyes_cat":"1f63b.png","heartbeat":"1f493.png","heartpulse":"1f497.png","heavy_heart_exclamation_mark_ornament":"2763-fe0f.png","hole":"1f573-fe0f.png","hot_face":"1f975.png","hugging_face":"1f917.png","hushed":"1f62f.png","imp":"1f47f.png","innocent":"1f607.png","japanese_goblin":"1f47a.png","japanese_ogre":"1f479.png","joy":"1f602.png","joy_cat":"1f639.png","kiss":"1f48b.png","kissing":"1f617.png","kissing_cat":"1f63d.png","kissing_closed_eyes":"1f61a.png","kissing_heart":"1f618.png","kissing_smiling_eyes":"1f619.png","laughing":"1f606.png","left_speech_bubble":"1f5e8-fe0f.png","love_letter":"1f48c.png","lying_face":"1f925.png","mask":"1f637.png","money_mouth_face":"1f911.png","nauseated_face":"1f922.png","nerd_face":"1f913.png","neutral_face":"1f610.png","no_mouth":"1f636.png","open_mouth":"1f62e.png","orange_heart":"1f9e1.png","partying_face":"1f973.png","pensive":"1f614.png","persevere":"1f623.png","pleading_face":"1f97a.png","pouting_cat":"1f63e.png","purple_heart":"1f49c.png","rage":"1f621.png","relaxed":"263a-fe0f.png","relieved":"1f60c.png","revolving_hearts":"1f49e.png","right_anger_bubble":"1f5ef-fe0f.png","robot_face":"1f916.png","rolling_on_the_floor_laughing":"1f923.png","scream":"1f631.png","scream_cat":"1f640.png","see_no_evil":"1f648.png","shushing_face":"1f92b.png","skull":"1f480.png","skull_and_crossbones":"2620-fe0f.png","sleeping":"1f634.png","sleepy":"1f62a.png","slightly_frowning_face":"1f641.png","slightly_smiling_face":"1f642.png","smile":"1f604.png","smile_cat":"1f638.png","smiley":"1f603.png","smiley_cat":"1f63a.png","smiling_face_with_3_hearts":"1f970.png","smiling_imp":"1f608.png","smirk":"1f60f.png","smirk_cat":"1f63c.png","sneezing_face":"1f927.png","sob":"1f62d.png","space_invader":"1f47e.png","sparkling_heart":"1f496.png","speak_no_evil":"1f64a.png","speech_balloon":"1f4ac.png","star-struck":"1f929.png","stuck_out_tongue":"1f61b.png","stuck_out_tongue_closed_eyes":"1f61d.png","stuck_out_tongue_winking_eye":"1f61c.png","sunglasses":"1f60e.png","sweat":"1f613.png","sweat_drops":"1f4a6.png","sweat_smile":"1f605.png","thinking_face":"1f914.png","thought_balloon":"1f4ad.png","tired_face":"1f62b.png","triumph":"1f624.png","two_hearts":"1f495.png","unamused":"1f612.png","upside_down_face":"1f643.png","weary":"1f629.png","white_frowning_face":"2639-fe0f.png","white_heart":"1f90d.png","wink":"1f609.png","woozy_face":"1f974.png","worried":"1f61f.png","yawning_face":"1f971.png","yellow_heart":"1f49b.png","yum":"1f60b.png","zany_face":"1f92a.png","zipper_mouth_face":"1f910.png","zzz":"1f4a4.png"},"enableQQ":false,"highlight":true,"lang":"zh-CN","pageSize":10,"placeholder":"你的评论 ...","recordIP":true,"serverURLs":"https://leancloud.hugoloveit.com","visitor":true}},"search":{"highlightTag":"em","lunrIndexURL":"/index.json","lunrLanguageCode":"zh","lunrSegmentitURL":"/lib/lunr/lunr.segmentit.js","maxResultLength":10,"noResultsFound":"没有找到结果","snippetLength":50,"type":"lunr"}};</script><script type="text/javascript" src="/js/theme.min.js"></script></body>
</html>
